package com.swk.common.util.file;

import com.swk.common.exception.SwkException;
import com.swk.common.util.http.HttpClientUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class FileUtil {
    private static final Logger logger = Logger.getLogger(FileUtil.class);
    @Autowired
    private static Environment env;
    /**
     * @param url
     * @param len
     * @return
     * @throws Exception
     */
    public static String contentRead(String url, String len) {
        File file = new File(url);
        if (!file.exists()) {
            return null;
        }
        FileInputStream fis = null;
        DataInputStream in = null;
        BufferedReader d = null;
        StringBuffer content = null;
        try {
            fis = new FileInputStream(url);
            content = new StringBuffer();
            in = new DataInputStream(fis);
            d = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            String line = null;
            while ((line = d.readLine()) != null)
                content.append("\n" + line);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {

        } finally {
            if (d != null) {
                try {
                    d.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        return content.toString();
    }

    /**
     * 获取文件的base64String数据
     *
     * @param path
     * @return
     */
    public static String base64read(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return null;
        }
        FileInputStream inputFile = null;
        try {
            inputFile = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
        byte[] buffer = new byte[(int) file.length()];
        try {
            inputFile.read(buffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        } finally {
            if (inputFile != null) {
                try {
                    inputFile.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return new BASE64Encoder().encode(buffer);
    }
    public static boolean checkPathExists(String path) {
        boolean flag = false;
        File file = new File(path);
        if (file.exists()) {
            flag = true;
        } else {
            flag = false;
        }
        return flag;
    }

    public static String decoderBase64File(String base64Code, String targetPath)
            throws SwkException {
        File file = new File(targetPath.substring(0,
                targetPath.lastIndexOf("/")));
        if (!file.exists()) {
            file.mkdirs();
            /*if(!flag){
                ConstUtil.changePathFlag();
			}*/
        }
        byte[] buffer = null;
        try {
            buffer = new BASE64Decoder().decodeBuffer(base64Code);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("decoderBase64File:[targetPath]:" + targetPath);
            logger.error("decoderBase64File:[Exception]:" + e.toString());
            throw new SwkException("base64数据解析失败" + targetPath);
        }

        FileOutputStream out = null;
        try {
            out = new FileOutputStream(targetPath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            logger.error("decoderBase64File:[targetPath]:" + targetPath);
            logger.error("decoderBase64File:[Exception]:" + e.toString());
            throw new SwkException("文件写入异常" + targetPath);
        }
        try {
            out.write(buffer);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("decoderBase64File:[targetPath]:" + targetPath);
            logger.error("decoderBase64File:[Exception]:" + e.toString());
            throw new SwkException("文件写入失败" + targetPath);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("decoderBase64File:[targetPath]:" + targetPath);
                    logger.error("decoderBase64File:[Exception]:" + e.toString());
                }
            }
        }
        return null;
    }

    public static String bufferFile(byte[] buffer, String targetPath)
            throws SwkException {
        File file = new File(targetPath.substring(0,
                targetPath.lastIndexOf("/")));
        if (!file.exists()) {
            file.mkdirs();
        }
        Boolean isException = false;

        FileOutputStream out = null;
        try {
            out = new FileOutputStream(targetPath);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "文件不存在" + e.getMessage();
        }
        try {
            out.write(buffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            isException = true;
            return "文件写入失败" + e.getMessage();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (isException) {
                throw new SwkException("文件写入异常" + targetPath);
            }
        }
        return null;
    }

    /**
     * 覆盖式写文件
     *
     * @param content
     * @param mkdirsPath
     * @param name
     * @return
     */
    public static String contentWrite(String content, String mkdirsPath,
                                      String name) {
        String filePath = mkdirsPath + "/" + name;
        File file1 = new File(mkdirsPath);
        if (!file1.exists()) {
            file1.mkdirs();
        }
        return contentWrite(content, filePath, false);
    }

    /**
     * @param content
     * @param filePath
     * @return
     */
    public static String contentWrite(String content, String filePath) {
        return contentWrite(content, filePath, false);
    }

    /**
     * 写文件
     *
     * @param content    写入内容
     * @param mkdirsPath 文件夹路径
     * @param name       文件名
     * @param isAddEndum 是否追加  false  覆盖  true  追加
     * @return
     */
    public static String contentWrite(String content, String mkdirsPath,
                                      String name, boolean isAddEndum) {
        String filePath = mkdirsPath + "/" + name;
        File file1 = new File(mkdirsPath);
        if (!file1.exists()) {
            file1.mkdirs();
        }
        return contentWrite(content, filePath, isAddEndum);
    }

    public static String contentWrite(String content, String filePath, boolean isAddEndum) {
        return contentWrite(content, filePath, isAddEndum, "UTF-8");
    }

    /**
     * 写文件
     *
     * @param content    写入内容
     * @param filePath   文件路径
     * @param isAddEndum 是否追加  false  覆盖  true  追加
     * @return
     */
    public static String contentWrite(String content, String filePath, boolean isAddEndum, String encording) {
        if (content == null) {
            return filePath;
        }
        FileOutputStream fos = null;
        Writer out = null;
        try {
            fos = new FileOutputStream(filePath, isAddEndum);
            out = new OutputStreamWriter(fos, encording);
            out.write(content);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
                if (fos != null) {
                    fos.flush();
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return filePath;
    }

    /**
     * 删除文件
     *
     * @param filePath String :/fqf.txt
     * @return boolean
     */
    public static void delFile(String filePath) {
        try {
            File f = new File(filePath);
            if (!f.exists()) {
                return;
            }
            filePath = filePath.toString();
            File myDelFile = new File(filePath);
            myDelFile.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * @param path1
     * @param name1
     * @param path2
     * @param name2
     * @return
     */
    public static boolean copy(String path1, String name1, String path2,
                               String name2) {
        return copy(path1 + name1, path2, name2);
    }

    public static boolean copy(String url, String path2, String name2) {
        File file1 = new File(url);
        if (!file1.exists()) {
            return false;
        }
        File file2 = new File(path2);
        if (!file2.exists()) {
            file2.mkdirs();
        }
        return copy(url, path2 + name2);
    }

    /**
     *
     * @param url
     * @param url2
     * @return
     */
    public static boolean copy(String url, String url2) {
        FileInputStream in1 = null;
        FileOutputStream out1 = null;
        try {

            File file_in = new File(url);
            if (!file_in.exists()) {
                return false;
            }
            File file_out = new File(url2);
            in1 = new FileInputStream(file_in);
            out1 = new FileOutputStream(file_out);
            byte[] bytes = new byte[1024];
            int c;
            while ((c = in1.read(bytes)) != -1)
                out1.write(bytes, 0, c);
            return true; // if success then return true
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (in1 != null) {
                    in1.close();
                }
                if (out1 != null) {
                    out1.flush();
                    out1.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 存储bytes数据
     *
     * @param bytes 数据流
     * @param url2  保存的路径
     * @return
     */
    public static boolean byteswrite(byte[] bytes, String url2) {
        FileOutputStream out1 = null;
        String url = url2.substring(0, url2.lastIndexOf("/"));
        File file = new File(url);
        if (!file.exists()) {
            file.mkdirs();
        }
        try {
            File file_out = new File(url2);
            out1 = new FileOutputStream(file_out);
            out1.write(bytes);
            return (true); // if success then return true
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (out1 != null) {
                    out1.flush();
                    out1.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * copy某个文件夹下的所有文件夹和文件
     *
     * @param frompath String
     * @param topath String
     * @throws java.io.FileNotFoundException
     * @throws java.io.IOException
     */
    public static void copyfiles(String frompath, String topath) {
        File file = new File(frompath);
        // 文件
        if (!file.isDirectory()) {
        } else if (file.isDirectory()) { // 如果是目录， 遍历所有子目录取出所有文件名
            String[] filelist = file.list();
            for (int i = 0; i < filelist.length; i++) {
                File readfile = new File(frompath + "/" + filelist[i]);
                if (!readfile.isDirectory()) {
                    copy(frompath + "/" + filelist[i], topath + "/",
                            filelist[i]);
                    // pathMap.put(pathMap.size(), readfile.getPath());
                } else if (readfile.isDirectory()) { // 子目录的目录
                    copyfiles(frompath + "/" + filelist[i], topath + "/"
                            + filelist[i]);
                }
            }
        }
    }

    /**
     * 读取某个文件夹下的所有文件夹和文件, 返回所有文件名
     *
     * @param frompath String
     * @return files
     * @throws java.io.FileNotFoundException
     * @throws java.io.IOException
     */
    public static List getFilesName(String frompath, List files) {
        File file = new File(frompath);
        // 文件
        if (!file.isDirectory()) {
        } else if (file.isDirectory()) { // 如果是目录， 遍历所有子目录取出所有文件名
            String[] filelist = file.list();
            for (int i = 0; i < filelist.length; i++) {
                File readfile = new File(frompath + "/" + filelist[i]);
                if (!readfile.isDirectory()) {
                    files.add(filelist[i]);
                } else if (readfile.isDirectory()) { // 子目录的目录
                    getFilesName(frompath + "/" + filelist[i], files);
                }
            }
        }
        return files;
    }

    /**
     * 删除某个文件夹下的所有文件夹和文件
     *
     * @param delpath String
     * @return boolean
     * @throws java.io.FileNotFoundException
     * @throws java.io.IOException
     */
    public static boolean deletefile(String delpath)
            throws FileNotFoundException, IOException {
        try {
            File file = new File(delpath);
            if (!file.isDirectory()) {
                System.out.println("1");
                file.delete();
            } else if (file.isDirectory()) {
                System.out.println("2");
                String[] filelist = file.list();
                for (int i = 0; i < filelist.length; i++) {
                    File delfile = new File(delpath + "" + filelist[i]);
                    if (!delfile.isDirectory()) {
                        System.out.println("path=" + delfile.getPath());
                        System.out.println("absolutepath="
                                + delfile.getAbsolutePath());
                        System.out.println("name=" + delfile.getName());
                        delfile.delete();
                        System.out.println("删除文件成功");
                    } else if (delfile.isDirectory()) {
                        deletefile(delpath + "" + filelist[i]);
                    }
                }
                file.delete();
            }
        } catch (FileNotFoundException e) {
            System.out.println("deletefile() Exception:" + e.getMessage());
        }
        return true;
    }

    /**
     * 读取某个文件夹下的所有文件夹和文件, 返回所有文件名
     *
     * @param filepath String
     * @return Map<Integer, String> pathMap
     * @throws java.io.FileNotFoundException
     * @throws java.io.IOException
     */
    public static Map<Integer, String> readfile(String filepath,
                                                Map<Integer, String> pathMap) throws Exception {
        if (pathMap == null) {
            pathMap = new HashMap<Integer, String>();
        }
        File file = new File(filepath);
        // 文件
        if (!file.isDirectory()) {
            pathMap.put(pathMap.size(), file.getPath());
        } else if (file.isDirectory()) { // 如果是目录， 遍历所有子目录取出所有文件名
            String[] filelist = file.list();
            for (int i = 0; i < filelist.length; i++) {
                File readfile = new File(filepath + "/" + filelist[i]);
                if (!readfile.isDirectory()) {
                    pathMap.put(pathMap.size(), readfile.getPath());
                } else if (readfile.isDirectory()) { // 子目录的目录
                    readfile(filepath + "/" + filelist[i], pathMap);
                }
            }
        }
        return pathMap;
    }

    /**
     * 获取文件的byte[]数据
     *
     * @param path
     * @return
     */
    public static byte[] bufferRead(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return null;
        }
        FileInputStream inputFile = null;
        try {
            inputFile = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
        byte[] buffer = new byte[(int) file.length()];
        try {
            inputFile.read(buffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        } finally {
            if (inputFile != null) {
                try {
                    inputFile.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return buffer;
    }

    public static String getFileName(List filesName, String name, int num) {
        boolean ishas = false;
        for (Object object : filesName) {
            if (object.toString().matches(
                    "^" + (num == 0 ? name : (name + "-" + num)) + "\\..+$")) {
                ishas = true;
            }
            if (ishas) {
                num++;
                getFileName(filesName, name, num);
                break;
            }
        }
        return name + "-" + num;
    }


    /**
     * 根据路径删除指定的目录或文件，无论存在与否
     *
     * @param sPath 要删除的目录或文件
     * @return 删除成功返回 true，否则返回 false。
     */
    public static boolean deleteFolder(String sPath) {
        File file = new File(sPath);
        Boolean flag = false;
        // 判断目录或文件是否存在
        if (!file.exists()) {  // 不存在返回 false
            return false;
        } else {
            // 判断是否为文件
            if (file.isFile()) {  // 为文件时调用删除文件方法
                return deleteFile(sPath, file, flag);
            } else {  // 为目录时调用删除目录方法
                return deleteDirectory(sPath, file, flag);
            }
        }
    }

    /**
     * 删除单个文件
     *
     * @param sPath 被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String sPath, File file, Boolean flag) {
        flag = false;
        file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     * 删除目录（文件夹）以及目录下的文件
     *
     * @param sPath 被删除目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String sPath, File file, Boolean flag) {
        flag = false;
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath(), file, flag);
                if (!flag) break;
            } //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath(), file, flag);
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    public static FileInputStream getFileStream(String path) {
        File file = new File(path);
        if (!file.exists() || file.isDirectory()) {
            return null;
        }
        FileInputStream inputFile = null;
        try {
            inputFile = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error("getFileStream param path=" + path + " ;Exception=" + e.toString());
            return null;
        }

        return inputFile;
    }

    /**
     * 判断文件是否有访问权限
     * @param file
     */
    public static boolean isReadable(File file) {
        FileInputStream fis = null;
        try{
            fis = new FileInputStream(file);
            if (fis.read() != -1) {
                return true;
            }
        }catch(Exception e) {
            e.printStackTrace();
        }finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return  false;
    }

    /**
     * 判断文件是否有访问权限
     * @param filePath
     */
    public static boolean isReadable(String filePath) {
        FileInputStream fis = null;
        try{
            fis = new FileInputStream(filePath);
            if (fis.read() != -1) {
                return true;
            }
        }catch(Exception e) {
            e.printStackTrace();
            logger.error("", e);
        }finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("", e);
                }
            }
        }
        return  false;
    }

    /**
     * 获取本地服务器上的文件
     * @param file
     * @return
     * @throws Exception
     */
    public static byte[] getFileBytesByFile(File file) throws Exception {
        // 在本地服务器
        byte[] pdfBytes = null;
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file);
            pdfBytes = IOUtils.toByteArray(inputStream);
        }catch(Exception e){
            e.printStackTrace();
            logger.error("", e);
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("", e);
                }
            }
        }
        return pdfBytes;
    }

//    /**
//     * 获取远程服务器上的文件
//     * @param filePath
//     * @return
//     * @throws Exception
//     */
//    public static byte[] getFileBytesByHttpPost(String filePath) throws Exception {
//        return getFileBytesByHttpPost(null,null, filePath);
//    }

    public static byte[] getFileBytesByHttpPost(String orderId, String fileId, String filePath) throws Exception {
        byte[] bytes = null;

        String httpFileServer1 = env.getProperty("http_file_server1");
        bytes = httpPostFileAction(httpFileServer1, orderId, fileId, filePath);
        if (bytes != null) {
            return bytes;
        }

        String httpFileServer2 = env.getProperty("http_file_server2");
        bytes = httpPostFileAction(httpFileServer2, orderId, fileId, filePath);
        if (bytes != null) {
            return bytes;
        }

        return null;
    }
    private static byte[] httpPostFileAction(String fileActionServer, String orderId, String fileId, String filePath) throws Exception {
        if (StringUtils.isNotBlank(fileActionServer)) {
            byte[] bytes = null;

            String url = "http://" + fileActionServer + ("/swk/file_get.do");
            com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
            jsonObject.put("orderId", orderId);
            jsonObject.put("fileId", fileId);
            jsonObject.put("filePath", filePath);
            HashMap<String, String> map = new HashMap<String, String>();
            map.put("url", url);
            map.put("postData", jsonObject.toJSONString());

            String p = HttpClientUtil.postURL(map);
            com.alibaba.fastjson.JSONObject jsonObject1 = com.alibaba.fastjson.JSONObject.parseObject(p);
            String base64 = jsonObject1.getString("data");
            if (base64 != null) {
                bytes = new BASE64Decoder().decodeBuffer(base64);
            }

            if (bytes != null) {
                return bytes;
            }
        }
        return null;
    }

}
